package org.codehaus.activemq.transport.jabber;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.Serializable;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.jms.JMSException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.activemq.message.ActiveMQBytesMessage;
import org.codehaus.activemq.message.ActiveMQMessage;
import org.codehaus.activemq.message.ActiveMQObjectMessage;
import org.codehaus.activemq.message.ActiveMQTextMessage;
import org.codehaus.activemq.message.Packet;
import org.codehaus.activemq.message.WireFormat;

public class JabberWireFormat extends WireFormat
{
  private static final Log log = LogFactory.getLog(JabberWireFormat.class);

  public WireFormat copy() {
    return new JabberWireFormat();
  }

  public Packet readPacket(DataInput in) throws IOException {
    return null;
  }

  public Packet readPacket(int firstByte, DataInput in) throws IOException {
    return null;
  }

  public void writePacket(Packet packet, DataOutput out) throws IOException, JMSException {
    switch (packet.getPacketType()) {
    case 6:
      writeMessage((ActiveMQMessage)packet, "", out);
      break;
    case 7:
      writeTextMessage((ActiveMQTextMessage)packet, out);
      break;
    case 9:
      writeBytesMessage((ActiveMQBytesMessage)packet, out);
      break;
    case 8:
      writeObjectMessage((ActiveMQObjectMessage)packet, out);
      break;
    case 10:
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
    case 16:
    case 17:
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
    case 24:
    case 25:
    case 26:
    default:
      log.warn("Ignoring message type: " + packet.getPacketType() + " packet: " + packet);
    }
  }

  protected void writeObjectMessage(ActiveMQObjectMessage message, DataOutput out)
    throws JMSException, IOException
  {
    Serializable object = message.getObject();
    String text = object != null ? object.toString() : "";
    writeMessage(message, text, out);
  }

  protected void writeTextMessage(ActiveMQTextMessage message, DataOutput out) throws JMSException, IOException {
    writeMessage(message, message.getText(), out);
  }

  protected void writeBytesMessage(ActiveMQBytesMessage message, DataOutput out) throws IOException {
    byte[] data = message.getBodyAsBytes();
    String text = encodeBinary(data);
    writeMessage(message, text, out);
  }

  protected void writeMessage(ActiveMQMessage message, String body, DataOutput out) throws IOException {
    String type = getXmppType(message);

    StringBuffer buffer = new StringBuffer("<");
    buffer.append(type);
    buffer.append(" to='");
    buffer.append(message.getJMSDestination().toString());
    buffer.append("' from='");
    buffer.append(message.getJMSReplyTo().toString());
    String messageID = message.getJMSMessageID();
    if (messageID != null) {
      buffer.append("' id='");
      buffer.append(messageID);
    }

    Hashtable properties = message.getProperties();
    Iterator iter;
    if (properties != null) {
      for (iter = properties.entrySet().iterator(); iter.hasNext(); ) {
        Map.Entry entry = (Map.Entry)iter.next();
        Object key = entry.getKey();
        Object value = entry.getValue();
        if (value != null) {
          buffer.append("' ");
          buffer.append(key.toString());
          buffer.append("='");
          buffer.append(value.toString());
        }
      }
    }

    buffer.append("'>");

    String id = message.getJMSCorrelationID();
    if (id != null) {
      buffer.append("<thread>");
      buffer.append(id);
      buffer.append("</thread>");
    }
    buffer.append(body);
    buffer.append("</");
    buffer.append(type);
    buffer.append(">");

    out.write(buffer.toString().getBytes());
  }

  protected String encodeBinary(byte[] data)
  {
    throw new RuntimeException("Not implemented yet!");
  }

  protected String getXmppType(ActiveMQMessage message) {
    String type = message.getJMSType();
    if (type == null) {
      type = "message";
    }
    return type;
  }
}